package com.jilefojing.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.jilefojing.beans.data.enums.ResponseEnum;
import com.jilefojing.beans.enums.ItemTypeEnumForSource;
import com.jilefojing.beans.enums.ProgressStatusForSource;
import com.jilefojing.beans.enums.ResolutionEnum;
import com.jilefojing.beans.enums.StatusEnumForPublish;
import com.jilefojing.beans.enums.forattitude.TypeEnumForAttitude;
import com.jilefojing.beans.enums.forrsourceuser.RelationTypeEnumForRSourceUser;
import com.jilefojing.beans.exception.UserContextException;
import com.jilefojing.beans.pojos.EVideo;
import com.jilefojing.beans.pojos.RCategorySource;
import com.jilefojing.beans.pojos.RTagSource;
import com.jilefojing.beans.pojos.Recommend;
import com.jilefojing.beans.pojos.base.BasePo;
import com.jilefojing.beans.pojos.enhanced.EnhancedAttitude;
import com.jilefojing.beans.pojos.enhanced.EnhancedDCategory;
import com.jilefojing.beans.pojos.enhanced.EnhancedEVideo;
import com.jilefojing.beans.pojos.enhanced.EnhancedRFavoriteSource;
import com.jilefojing.beans.pojos.enhanced.EnhancedRSourceUser;
import com.jilefojing.beans.pojos.enhanced.EnhancedRTagSource;
import com.jilefojing.beans.pojos.enhanced.EnhancedStatistics;
import com.jilefojing.beans.pojos.enhanced.EnhancedTag;
import com.jilefojing.beans.pojos.enhanced.EnhancedUser;
import com.jilefojing.beans.pojos.enhanced.base.BaseEnhanced;
import com.jilefojing.beans.query.EVideoQuery;
import com.jilefojing.beans.vo.Order;
import com.jilefojing.beans.vo.Pagination;
import com.jilefojing.beans.vo.PlayTypeForEVideo;
import com.jilefojing.beans.vo.UploadFile;
import com.jilefojing.context.beans.vo.UserContext;
import com.jilefojing.dao.IEVideoDao;
import com.jilefojing.dao.IRCategorySourceDao;
import com.jilefojing.dao.IRTagSourceDao;
import com.jilefojing.dao.IRecommendDao;
import com.jilefojing.dao.IStatisticsDao;
import com.jilefojing.qiniu.beans.enums.BucketEnum;
import com.jilefojing.qiniu.beans.enums.BucketEnum.BucketEnumExtral_SourceEnum;
import com.jilefojing.service.IAttitudeService;
import com.jilefojing.service.IDCategoryService;
import com.jilefojing.service.IEVideoService;
import com.jilefojing.service.IRCategorySourceService;
import com.jilefojing.service.IRFavoriteSourceService;
import com.jilefojing.service.IRSourceCorrelationService;
import com.jilefojing.service.IRSourceUserService;
import com.jilefojing.service.IRTagSourceService;
import com.jilefojing.service.ISourceService;
import com.jilefojing.service.IStatisticsService;
import com.jilefojing.service.ITagService;
import com.jilefojing.service.IUserService;
import com.jilefojing.service.base.impl.BaseService;
import com.jilefojing.util.Detect;
import com.jilefojing.util.PropertyFileUtil;
import com.jilefojing.util.QiniuUtil;

/**
 * 
 * @author 作者 jgshun
 * @date 创建时间 2016年07月19日 13时23分08秒
 */
@Service
public class EVideoService extends BaseService<EVideo> implements IEVideoService {
	@Autowired
	private IEVideoDao eVideoDao;
	@Autowired
	private IStatisticsService statisticsService;
	@Autowired
	private IRSourceUserService rSourceUserService;
	@Autowired
	private IUserService userService;
	@Autowired
	private IAttitudeService attitudeService;
	@Autowired
	private IRFavoriteSourceService rFavoriteSourceService;
	@Autowired
	private IRTagSourceService rTagSourceService;
	@Autowired
	private ITagService tagService;
	@Autowired
	private IRSourceCorrelationService rSourceCorrelationService;
	@Autowired
	private ISourceService sourceService;
	@Autowired
	private IDCategoryService dCategoryService;
	@Autowired
	private IRCategorySourceService rCategorySourceService;
	@Autowired
	private IRCategorySourceDao rCategorySourceDao;
	@Autowired
	private IRTagSourceDao rTagSourceDao;
	@Autowired
	private IStatisticsDao statisticsDao;
	@Autowired
	private IRecommendDao recommendDao;

	private static final Logger _Logger = LoggerFactory.getLogger(EVideoService.class);

	@Override
	public Pagination<EnhancedEVideo> getPagination(EVideoQuery eVideoQuery, Pagination<EnhancedEVideo> pagination, UserContext userContext) {
		@SuppressWarnings("unchecked")
		Pagination<EVideo> bannerPagination = eVideoDao.getPagination(eVideoQuery, pagination.copy());
		pagination.setCount(bannerPagination.getCount());
		if (!Detect.notEmpty(bannerPagination.getItems())) {
			return pagination;
		}
		List<EnhancedEVideo> enhancedEVideos = this.convent2Enhanceds(bannerPagination.getItems());
		this.appendEnhancedCommons(enhancedEVideos, userContext);
		pagination.setItems(enhancedEVideos);
		return pagination;
	}

	@Override
	public List<EnhancedEVideo> convent2Enhanceds(List<? extends BasePo> pos) {
		@SuppressWarnings("unchecked")
		List<EVideo> eVideos = (List<EVideo>) pos;

		List<EnhancedEVideo> enhancedEVideos = new ArrayList<EnhancedEVideo>();
		for (EVideo _EVideo : eVideos) {
			if (Detect.notEmpty(_EVideo.getCoverUrl()) && !_EVideo.getCoverUrl().startsWith(SCHEMA)) {
				_EVideo.setCoverUrl(QiniuUtil.getImagesDomain() + "/" + _EVideo.getCoverUrl());
			}

			enhancedEVideos.add(new EnhancedEVideo(_EVideo));
		}

		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (_EnhancedEVideo.getSkey() != null && _EnhancedEVideo.getSkey().length() > 0) {
				List<PlayTypeForEVideo> playTypes = new ArrayList<PlayTypeForEVideo>();
				if (_EnhancedEVideo.getSources() != null && _EnhancedEVideo.getSources().length() > 0) {
					String[] sourceSplits = _EnhancedEVideo.getSources().split(",");
					for (String source : sourceSplits) {
						String[] types = source.split("_");
						ResolutionEnum resolution = ResolutionEnum.getResolutionByTypeAndResolution(types[0], types[1]);

						PlayTypeForEVideo playTypeForEVideo = new PlayTypeForEVideo();
						playTypeForEVideo.setResolution(resolution.getResolution());
						playTypeForEVideo.setType(resolution.getType());

						int _lastI = _EnhancedEVideo.getSkey().lastIndexOf("/");
						String _prefix = _EnhancedEVideo.getSkey().substring(0, _lastI + 1);
						String _suffix = _EnhancedEVideo.getSkey().substring(_lastI + 1);

						StringBuilder urlBud = new StringBuilder();
						urlBud.append(_prefix).append(resolution.getType()).append("/").append(resolution.getResolution()).append("/").append(_suffix);

						playTypeForEVideo.setUrl(QiniuUtil.getVideosDomain() + urlBud.toString());
						playTypes.add(playTypeForEVideo);
					}
				} else {
					PlayTypeForEVideo playTypeForEVideo = new PlayTypeForEVideo();

					if (!_EnhancedEVideo.getSkey().startsWith(SCHEMA)) {
						playTypeForEVideo.setUrl(QiniuUtil.getVideosDomain() + _EnhancedEVideo.getSkey());
					} else {
						playTypeForEVideo.setUrl(_EnhancedEVideo.getSkey());
					}

					playTypeForEVideo.setResolution(ResolutionEnum.DEFAULT.getResolution());
					playTypeForEVideo.setType(ResolutionEnum.DEFAULT.getType());
					playTypes.add(playTypeForEVideo);
				}

				_EnhancedEVideo.setPlayTypes(playTypes);
			}
		}
		return enhancedEVideos;
	}

	@Override
	public EnhancedEVideo appendEnhancedStatistics(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedStatistics(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedStatistics(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> videoIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			videoIds.add(_EnhancedEVideo.getId());
		}
		List<EnhancedStatistics> enhancedStatisticses = statisticsService.getEnhancedStatisticses(ItemTypeEnumForSource.VIDEO, videoIds, userContext);

		if (Detect.notEmpty(enhancedStatisticses)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				for (EnhancedStatistics _EnhancedStatistics : enhancedStatisticses) {
					if (_EnhancedStatistics.getEnhancedItem() != null) {
						if (_EnhancedEVideo.getId() == ((EnhancedEVideo) _EnhancedStatistics.getEnhancedItem()).getId()) {
							_EnhancedEVideo.setEnhancedStatistics(_EnhancedStatistics);
							break;
						}
					}
				}
			}
		}
		return enhancedEVideos;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedCommons(List<? extends BaseEnhanced> enhancedItems, UserContext userContext) {
		@SuppressWarnings("unchecked")
		List<EnhancedEVideo> enhancedEVideos = (List<EnhancedEVideo>) enhancedItems;
		this.appendEnhancedStatistics(enhancedEVideos, userContext);
		this.appendCountCognate(enhancedEVideos, userContext);
		this.appendCountCognatePlaytime(enhancedEVideos, userContext);
		this.appendEnhancedUsers(enhancedEVideos, userContext);
		this.appendEnhancedTags(enhancedEVideos, userContext);
		return enhancedEVideos;
	}

	@Override
	public List<EnhancedEVideo> appendCountCognatePlaytime(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> isEntityIds = new ArrayList<Long>();
		List<Long> notEntityIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (!_EnhancedEVideo.isEntity()) {
				notEntityIds.add(_EnhancedEVideo.getId());
			} else if (_EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
				isEntityIds.add(_EnhancedEVideo.getEnhancedParent().getId());
			} else {
				_EnhancedEVideo.setCountCognate(1);
			}
		}
		if (Detect.notEmpty(isEntityIds)) {
			this.appendCountCognatePlaytime_IsEntity(isEntityIds, enhancedEVideos, userContext);
		}

		if (Detect.notEmpty(notEntityIds)) {
			this.appendCountCognatePlaytime_NotEntityIds(notEntityIds, enhancedEVideos, userContext);
		}
		return enhancedEVideos;
	}

	private void appendCountCognatePlaytime_NotEntityIds(List<Long> notEntityIds, List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eVideoDao.countCognatePlaytimeByParentIds(notEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				if (!_EnhancedEVideo.isEntity()) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEVideo.getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEVideo.setCountCognatePlaytime(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}

	}

	private void appendCountCognatePlaytime_IsEntity(List<Long> isEntityIds, List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eVideoDao.countCognatePlaytimeByParentIds(isEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEVideo.getEnhancedParent().getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEVideo.setCountCognatePlaytime(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}

	}

	@Override
	public EnhancedEVideo getEnhanced(long id, UserContext userContext) {
		List<EnhancedEVideo> enhancedEVideos = this.getEnhanceds(Arrays.asList(new Long[] { id }), userContext);
		if (!Detect.notEmpty(enhancedEVideos)) {
			return null;
		}
		return enhancedEVideos.get(0);
	}

	@Override
	public List<EnhancedEVideo> getEnhanceds(List<Long> ids, UserContext userContext) {
		List<EVideo> eVideos = eVideoDao.getListByIds(ids);
		if (!Detect.notEmpty(eVideos)) {
			return null;
		}
		List<EnhancedEVideo> enhancedEVideos = this.convent2Enhanceds(eVideos);
		this.appendEnhancedCommons(enhancedEVideos, userContext);
		return enhancedEVideos;
	}

	@Override
	public List<EnhancedEVideo> getEnhancedsNotAppend(List<Long> ids, UserContext userContext) {
		List<EVideo> eVideos = eVideoDao.getListByIds(ids);
		if (!Detect.notEmpty(eVideos)) {
			return null;
		}
		return this.convent2Enhanceds(eVideos);
	}

	@Override
	public EnhancedEVideo appendEnhancedChildren(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedChildren(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedChildren(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> parentIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (!_EnhancedEVideo.isEntity()) {// 是视频集合
				parentIds.add(_EnhancedEVideo.getId());
			}
		}

		if (Detect.notEmpty(parentIds)) {
			List<EnhancedEVideo> enhancedChildEVideos = this.getEnhancedsByParentIds(parentIds, userContext);
			if (Detect.notEmpty(enhancedChildEVideos)) {
				for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
					if (!_EnhancedEVideo.isEntity()) {
						_EnhancedEVideo.setEnhancedChildren(this.getEnhancedEVideosForParent(_EnhancedEVideo, enhancedChildEVideos));
					}
				}
			}
		}
		return enhancedEVideos;
	}

	@Override
	public List<EnhancedEVideo> getEnhancedsByParentId(long parentId, UserContext userContext) {
		return this.getEnhancedsByParentIds(Arrays.asList(new Long[] { parentId }), userContext);
	}

	@Override
	public List<EnhancedEVideo> getEnhancedsByParentIds(List<Long> parentIds, UserContext userContext) {
		List<EVideo> eVideos = eVideoDao.getListByParentIds(parentIds);
		if (!Detect.notEmpty(eVideos)) {
			return null;
		}
		List<EnhancedEVideo> enhancedEVideos = this.convent2Enhanceds(eVideos);
		this.appendEnhancedCommons(enhancedEVideos, userContext);
		return enhancedEVideos;
	}

	private List<EnhancedEVideo> getEnhancedEVideosForParent(EnhancedEVideo enhancedParentEVideo, List<EnhancedEVideo> enhancedChildEVideos) {
		List<EnhancedEVideo> curEnhancedChildEVideos = new ArrayList<EnhancedEVideo>();
		for (EnhancedEVideo _EnhancedChildEVideo : enhancedChildEVideos) {
			if (enhancedParentEVideo.getId() == _EnhancedChildEVideo.getEnhancedParent().getId()) {
				curEnhancedChildEVideos.add(_EnhancedChildEVideo);
			}
		}

		return curEnhancedChildEVideos;
	}

	@Override
	public EnhancedEVideo appendEnhancedParent(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedParent(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedParent(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> parentIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
				parentIds.add(_EnhancedEVideo.getEnhancedParent().getId());
			}
		}
		if (Detect.notEmpty(parentIds)) {
			List<EnhancedEVideo> enhancedParentEVideos = this.getEnhanceds(parentIds, userContext);
			if (Detect.notEmpty(enhancedParentEVideos)) {
				this.appendEnhancedParentEVideos(enhancedEVideos, enhancedParentEVideos, userContext);
			}
		}
		return enhancedEVideos;
	}

	private void appendEnhancedParentEVideos(List<EnhancedEVideo> enhancedEVideos, List<EnhancedEVideo> enhancedParentEVideos, UserContext userContext) {
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
				for (EnhancedEVideo _enhancedParentEVideo : enhancedParentEVideos) {
					if (_EnhancedEVideo.getEnhancedParent().getId() == _enhancedParentEVideo.getId()) {
						_EnhancedEVideo.setEnhancedParent(_enhancedParentEVideo);
						break;
					}
				}
			}
		}
	}

	@Override
	public EnhancedEVideo appendCountCognate(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendCountCognate(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendCountCognate(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> isEntityIds = new ArrayList<Long>();
		List<Long> notEntityIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (!_EnhancedEVideo.isEntity()) {
				notEntityIds.add(_EnhancedEVideo.getId());
			} else if (_EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
				isEntityIds.add(_EnhancedEVideo.getEnhancedParent().getId());
			} else {
				_EnhancedEVideo.setCountCognate(1);
			}
		}
		if (Detect.notEmpty(isEntityIds)) {
			this.appendCountCognate_IsEntity(isEntityIds, enhancedEVideos, userContext);
		}

		if (Detect.notEmpty(notEntityIds)) {
			this.appendCountCognate_NotEntityIds(notEntityIds, enhancedEVideos, userContext);
		}
		return enhancedEVideos;
	}

	private void appendCountCognate_NotEntityIds(List<Long> notEntityIds, List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eVideoDao.countCognatesByParentIds(notEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				if (!_EnhancedEVideo.isEntity()) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEVideo.getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEVideo.setCountCognate(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}

	}

	private void appendCountCognate_IsEntity(List<Long> isEntityIds, List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Map<String, Integer>> countCognates = eVideoDao.countCognatesByParentIds(isEntityIds);
		if (Detect.notEmpty(countCognates)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
					for (Map<String, Integer> _CountCognate : countCognates) {
						if (_EnhancedEVideo.getEnhancedParent().getId() == Long.valueOf(String.valueOf(_CountCognate.get("parentId")))) {
							_EnhancedEVideo.setCountCognate(Integer.valueOf(String.valueOf(_CountCognate.get("count"))));
							break;
						}
					}
				}
			}
		}
	}

	@Override
	public EnhancedEVideo getEnhancedForActive(long id, UserContext userContext) throws UserContextException {
		EnhancedEVideo enhancedEVideo = this.getEnhanced(id, userContext);
		if (enhancedEVideo == null) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}

		if (enhancedEVideo.getStatus() != StatusEnumForPublish.ALREADY_RELEASED) {
			throw new UserContextException(ResponseEnum.SOURCE_INVALID);
		}

		if (!enhancedEVideo.isEntity()) {
			// TODO 待优化 如果用户从视频集进来的 就调到用户最后一次看的视频
			List<EnhancedEVideo> enhancedEVideos = this.getEnhancedsByParentId(id, userContext);
			if (!Detect.notEmpty(enhancedEVideos)) {
				throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
			}
			enhancedEVideo = enhancedEVideos.get(0);
		}

		return enhancedEVideo;
	}

	@Override
	public EnhancedEVideo appendEnhancedUsers(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedUsers(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedUsers(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> videoIds = new ArrayList<Long>();
		List<Long> createUserIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			videoIds.add(_EnhancedEVideo.getId());
			createUserIds.add(_EnhancedEVideo.getEnhancedCreateUser().getId());
		}
		List<EnhancedRSourceUser> enhancedRSourceUsers = rSourceUserService.getEnhanceds(ItemTypeEnumForSource.VIDEO, videoIds, userContext);

		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			EnhancedUser owner = null;
			if (Detect.notEmpty(enhancedRSourceUsers)) {
				owner = this.getEnhancedOwnerUser(enhancedRSourceUsers, _EnhancedEVideo);
			}
			if (owner == null) {
				// 默认属于系统用户
				owner = super._ENHANCE_SYSTEM_USER_;
				if (owner == null) {
					owner = userService.getEnhancedUser(PropertyFileUtil.getLongValue("system_user_id"));
					super._ENHANCE_SYSTEM_USER_ = owner;
				}
			}
			_EnhancedEVideo.setEnhancedOwner(owner);
		}

		List<EnhancedUser> enhancedCreateUser = userService.getEnhancedUsers(createUserIds);
		if (Detect.notEmpty(enhancedCreateUser)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				for (EnhancedUser _EnhancedUser : enhancedCreateUser) {
					if (_EnhancedEVideo.getEnhancedCreateUser().getId() == _EnhancedUser.getId()) {
						_EnhancedEVideo.setEnhancedCreateUser(_EnhancedUser);
						break;
					}
				}
			}
		}
		return enhancedEVideos;
	}

	private EnhancedUser getEnhancedOwnerUser(List<EnhancedRSourceUser> enhancedRSourceUsers, EnhancedEVideo enhancedEVideo) {
		for (EnhancedRSourceUser _EnhancedRSourceUser : enhancedRSourceUsers) {
			if (enhancedEVideo.getId() == ((EnhancedEVideo) _EnhancedRSourceUser.getEnhancedItem()).getId() && _EnhancedRSourceUser.getRelationType() == RelationTypeEnumForRSourceUser.OWNER) {
				return _EnhancedRSourceUser.getEnhancedUser();
			}
		}
		return null;
	}

	@Override
	public EnhancedEVideo appendEnhancedAttitudeForUser(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedAttitudeForUser(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedAttitudeForUser(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> videoIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			videoIds.add(_EnhancedEVideo.getId());
		}

		List<EnhancedAttitude> enhancedAttitudes = attitudeService.getEnhancedAttitudesByItemsForUser(ItemTypeEnumForSource.VIDEO, videoIds, TypeEnumForAttitude.PRAISE, userContext);
		if (Detect.notEmpty(enhancedAttitudes)) {
			for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
				for (EnhancedAttitude _EnhancedAttitude : enhancedAttitudes) {
					if (_EnhancedEVideo.getId() == ((EnhancedEVideo) _EnhancedAttitude.getEnhancedItem()).getId()) {
						_EnhancedEVideo.setEnhancedAttitude(_EnhancedAttitude);
						break;
					}
				}
			}
		}
		return enhancedEVideos;
	}

	@Override
	public EnhancedEVideo appendEnhancedRFavoriteSourceForUser(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedRFavoriteSourceForUser(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedRFavoriteSourceForUser(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> videoIds = new ArrayList<Long>();
		List<Long> paretnVideoIds = new ArrayList<Long>();

		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
				paretnVideoIds.add(_EnhancedEVideo.getEnhancedParent().getId());
			} else {
				videoIds.add(_EnhancedEVideo.getId());
			}
		}
		if (Detect.notEmpty(videoIds)) {
			List<EnhancedRFavoriteSource> enhancedRFavoriteSources = rFavoriteSourceService.getEnhancedRFavoriteSourcesByItemsForUser(ItemTypeEnumForSource.VIDEO, videoIds, userContext);
			if (Detect.notEmpty(enhancedRFavoriteSources)) {
				for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
					if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
					} else {
						for (EnhancedRFavoriteSource _EnhancedRFavoriteSource : enhancedRFavoriteSources) {
							if (_EnhancedEVideo.getId() == ((EnhancedEVideo) _EnhancedRFavoriteSource.getEnhancedItem()).getId()) {
								_EnhancedEVideo.setEnhancedRFavoriteSource(_EnhancedRFavoriteSource);
								break;
							}
						}
					}
				}
			}
		}

		if (Detect.notEmpty(paretnVideoIds)) {
			List<EnhancedRFavoriteSource> enhancedRFavoriteSources = rFavoriteSourceService.getEnhancedRFavoriteSourcesByItemsForUser(ItemTypeEnumForSource.VIDEO, paretnVideoIds, userContext);
			if (Detect.notEmpty(enhancedRFavoriteSources)) {
				for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
					if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null && _EnhancedEVideo.getEnhancedParent().getId() > 0) {
						for (EnhancedRFavoriteSource _EnhancedRFavoriteSource : enhancedRFavoriteSources) {
							if (_EnhancedEVideo.getId() == ((EnhancedEVideo) _EnhancedRFavoriteSource.getEnhancedItem()).getId()) {
								_EnhancedEVideo.setEnhancedRFavoriteSource(_EnhancedRFavoriteSource);
								break;
							}
						}
					}
				}
			}
		}
		return enhancedEVideos;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<EnhancedEVideo> appendEnhancedExtralsForUser(List<? extends BaseEnhanced> enhancedItems, UserContext userContext) {
		this.appendEnhancedAttitudeForUser((List<EnhancedEVideo>) enhancedItems, userContext);
		this.appendEnhancedRFavoriteSourceForUser((List<EnhancedEVideo>) enhancedItems, userContext);
		return (List<EnhancedEVideo>) enhancedItems;
	}

	@Override
	public EnhancedEVideo appendEnhancedTags(EnhancedEVideo enhancedEVideo, UserContext userContext) {
		this.appendEnhancedTags(Arrays.asList(new EnhancedEVideo[] { enhancedEVideo }), userContext);
		return enhancedEVideo;
	}

	@Override
	public List<EnhancedEVideo> appendEnhancedTags(List<EnhancedEVideo> enhancedEVideos, UserContext userContext) {
		List<Long> videoIds = new ArrayList<Long>();
		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			videoIds.add(_EnhancedEVideo.getId());
			if (_EnhancedEVideo.isEntity() && _EnhancedEVideo.getEnhancedParent() != null) {
				videoIds.add(_EnhancedEVideo.getEnhancedParent().getId());
			}
		}

		List<EnhancedRTagSource> enhancedRTagSources = rTagSourceService.getEnhancedRTagSourcesByItems(ItemTypeEnumForSource.VIDEO, videoIds, userContext);
		if (!Detect.notEmpty(enhancedRTagSources)) {
			return enhancedEVideos;
		}
		rTagSourceService.appendEnhancedTags2EnhancedRTagSources(enhancedRTagSources, userContext);

		for (EnhancedEVideo _EnhancedEVideo : enhancedEVideos) {
			_EnhancedEVideo.setEnhancedTags(this.getCurEnhancedTags(_EnhancedEVideo, enhancedRTagSources));
		}
		return enhancedEVideos;
	}

	private List<EnhancedTag> getCurEnhancedTags(EnhancedEVideo enhancedEVideo, List<EnhancedRTagSource> enhancedRTagSources) {
		Set<Long> curTagIds = new HashSet<Long>();
		List<EnhancedTag> curEnhancedTags = new ArrayList<EnhancedTag>();
		for (EnhancedRTagSource _EnhancedRTagSource : enhancedRTagSources) {
			long itemId = _EnhancedRTagSource.getEnhancedItem().getDynamicId();
			if (!curTagIds.contains(_EnhancedRTagSource.getEnhancedTag().getId())) {
				if (itemId == enhancedEVideo.getId()) {
					curEnhancedTags.add(_EnhancedRTagSource.getEnhancedTag());
				}
				if (enhancedEVideo.isEntity() && enhancedEVideo.getEnhancedParent() != null && itemId == enhancedEVideo.getEnhancedParent().getId()) {
					curEnhancedTags.add(_EnhancedRTagSource.getEnhancedTag());
				}
				curTagIds.add(_EnhancedRTagSource.getEnhancedTag().getId());
			}
		}
		return curEnhancedTags;
	}

	@Override
	public Pagination<EnhancedEVideo> getPaginationByCategoryIdsForActive(List<Long> categoryIds, List<ProgressStatusForSource> progressStatuses, Pagination<EnhancedEVideo> pagination,
			UserContext userContext) {
		if (!Detect.notEmpty(pagination.getOrders())) {
			pagination.addOrder(new Order(RCategorySource.COLUMN_SORT, Order.ORDER_DESC));
		}
		@SuppressWarnings("unchecked")
		Pagination<? extends BaseEnhanced> baseEnhancedPagination = sourceService.getPaginationByCategoryIdsForActive(categoryIds,
				Arrays.asList(new ItemTypeEnumForSource[] { ItemTypeEnumForSource.VIDEO }), Arrays.asList(new StatusEnumForPublish[] { StatusEnumForPublish.ALREADY_RELEASED }), progressStatuses,
				pagination.copy(), userContext);
		pagination.setCount(baseEnhancedPagination.getCount());
		if (!Detect.notEmpty(baseEnhancedPagination.getItems())) {
			return pagination;
		}

		pagination.setItems((List<EnhancedEVideo>) baseEnhancedPagination.getItems());
		return pagination;
	}

	@Override
	public Pagination<EnhancedEVideo> getPaginationByTagIdForActive(long tagId, Pagination<EnhancedEVideo> pagination, UserContext userContext) {
		@SuppressWarnings("unchecked")
		Pagination<? extends BaseEnhanced> baseEnhancedPagination = sourceService.getPaginationByTagIds(Arrays.asList(new Long[] { tagId }),
				Arrays.asList(new ItemTypeEnumForSource[] { ItemTypeEnumForSource.VIDEO }), Arrays.asList(new StatusEnumForPublish[] { StatusEnumForPublish.ALREADY_RELEASED }), pagination.copy(),
				userContext);

		pagination.setCount(baseEnhancedPagination.getCount());
		if (!Detect.notEmpty(baseEnhancedPagination.getItems())) {
			return pagination;
		}

		pagination.setItems((List<EnhancedEVideo>) baseEnhancedPagination.getItems());
		return pagination;
	}

	@Override
	public List<EnhancedDCategory> getEnhancedDCategories(UserContext userContext) {
		List<EnhancedDCategory> topEnhancedDCategories = dCategoryService.getEnhancedTopDCategoriesByItemType(ItemTypeEnumForSource.VIDEO, userContext);
		dCategoryService.appendEnhancedChildDCategories2EnhancedDCategories(topEnhancedDCategories, userContext);
		return topEnhancedDCategories;
	}

	@Override
	public EVideo updateCover(long id, UploadFile coverUploadFile, UserContext userContext) throws UserContextException {
		EVideo eVideo = eVideoDao.getById(id);
		Date now = new Date();

		Detect.checkImgType(coverUploadFile.getSuffix());

		eVideo.setCoverUrl(QiniuUtil.upload(coverUploadFile, BucketEnum.IMG, BucketEnumExtral_SourceEnum.VIDEO_COVER));
		eVideo.setUpdateTime(now);
		return eVideoDao.updateByPrimaryKey(eVideo);
	}

	@Override
	public EVideo add(EVideo eVideo, UserContext userContext) throws UserContextException {
		Date now = new Date();
		if (!Detect.notEmpty(eVideo.getTitle())) {
			throw new UserContextException("[标题不能为空]");
		} else if (eVideo.getTitle().trim().length() > 50) {
			throw new UserContextException("[标题不能超过50字]");
		}
		if (Detect.notEmpty(eVideo.getSummary()) && eVideo.getSummary().trim().length() > 200) {
			throw new UserContextException("[简介不能超过200字]");
		}
		// if (eVideo.getEntity() == 1 && !Detect.notEmpty(eVideo.getSkey())) {
		// throw new UserContextException("[视频资源不能为空]");
		// }
		if (eVideo.getEntity() == 1 && !Detect.notEmpty(eVideo.getTudouCode())) {
			throw new UserContextException("[土豆代码不能为空]");
		}
		if (!Detect.notEmpty(eVideo.getCoverUrl())) {
			throw new UserContextException("[封面资源不能为空]");
		}
		eVideo.setId(null);
		eVideo.setCreateTime(now);
		eVideo.setUpdateTime(now);
		eVideo.setCreateUser(userContext.getUserId());
		eVideo.setStatus(StatusEnumForPublish.PENDING_RELEASE.getCode());
		eVideo.setProgressStatus(ProgressStatusForSource.SERIALISE.getCode());

		return eVideoDao.saveSelective(eVideo);
	}

	@Override
	public EVideo update(EVideo eVideo, UserContext userContext) throws UserContextException {
		EVideo dbEVideo = eVideoDao.getById(eVideo.getId());
		if (dbEVideo == null) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}
		if (!Detect.notEmpty(eVideo.getTitle())) {
			throw new UserContextException("[标题不能为空]");
		}
		if (eVideo.getStatus() == null || StatusEnumForPublish.getStatusEnumByCode(eVideo.getStatus()) == null) {
			throw new UserContextException("[状态不能为空/不存在]");
		}

		if (eVideo.getProgressStatus() == null || ProgressStatusForSource.getProgressStatusEnumByCode(eVideo.getProgressStatus()) == null) {
			throw new UserContextException("[进度不能为空/不存在]");
		}

		Date now = new Date();

		dbEVideo.setTitle(eVideo.getTitle());
		dbEVideo.setSort(eVideo.getSort());
		dbEVideo.setPlaytime(eVideo.getPlaytime());
		dbEVideo.setSummary(eVideo.getSummary());
		dbEVideo.setInfo(eVideo.getInfo());
		dbEVideo.setStatus(StatusEnumForPublish.getStatusEnumByCode(eVideo.getStatus()).getCode());
		dbEVideo.setUpdateTime(now);
		dbEVideo.setProgressStatus(eVideo.getProgressStatus());

		if ((dbEVideo.getEntity() == null || dbEVideo.getEntity() == 0) && eVideo.getStatus() == StatusEnumForPublish.ALREADY_RELEASED.getCode()) {
			EnhancedEVideo dbEnhancedEVideo = new EnhancedEVideo(dbEVideo);
			this.appendEnhancedChildren(dbEnhancedEVideo, userContext);
			if (!Detect.notEmpty(dbEnhancedEVideo.getEnhancedChildren())) {
				throw new UserContextException("[此视频集中没有任何视频,不能发布]");
			}
		}

		if (dbEVideo.getEntity() == null || dbEVideo.getEntity() == 0) {// 集合
																		// 关联更新子视频进度
			List<EVideo> dbChildren = eVideoDao.getListByParentId(dbEVideo.getId());
			if (Detect.notEmpty(dbChildren)) {
				List<Long> childIds = new ArrayList<Long>();

				for (EVideo _dbChild : dbChildren) {
					_dbChild.setProgressStatus(dbEVideo.getProgressStatus());
					eVideoDao.updateByPrimaryKey(_dbChild);

					childIds.add(_dbChild.getId());
				}

				List<Recommend> dbRecommends = recommendDao.getListByItems(ItemTypeEnumForSource.VIDEO, childIds);
				if (Detect.notEmpty(dbRecommends)) {
					for (Recommend _Recommend : dbRecommends) {
						_Recommend.setStatus(eVideo.getStatus());
						_Recommend.setProgressStatus(dbEVideo.getProgressStatus());
						_Recommend.setUpdateTime(now);

						recommendDao.updateByPrimaryKeySelective(_Recommend);
					}
				}

				List<RCategorySource> rCategorySources = rCategorySourceDao.getListByItems(ItemTypeEnumForSource.VIDEO, childIds);
				if (Detect.notEmpty(rCategorySources)) {
					for (RCategorySource _RCategorySource : rCategorySources) {
						_RCategorySource.setStatus(dbEVideo.getStatus());
						_RCategorySource.setProgressStatus(dbEVideo.getProgressStatus());
						_RCategorySource.setUpdateTime(now);

						rCategorySourceDao.updateByPrimaryKeySelective(_RCategorySource);
					}
				}

				List<RTagSource> rTagSources = rTagSourceDao.getListByItems(ItemTypeEnumForSource.VIDEO, childIds);
				if (Detect.notEmpty(rTagSources)) {
					for (RTagSource _RTagSource : rTagSources) {
						_RTagSource.setStatus(eVideo.getStatus());
						_RTagSource.setProgressStatus(dbEVideo.getProgressStatus());
						_RTagSource.setUpdateTime(now);

						rTagSourceDao.updateByPrimaryKeySelective(_RTagSource);
					}
				}

			}
		}

		List<RCategorySource> rCategorySources = rCategorySourceDao.getListByItem(ItemTypeEnumForSource.VIDEO, eVideo.getId());
		if (Detect.notEmpty(rCategorySources)) {
			for (RCategorySource _RCategorySource : rCategorySources) {
				_RCategorySource.setStatus(dbEVideo.getStatus());
				_RCategorySource.setProgressStatus(dbEVideo.getProgressStatus());
				_RCategorySource.setUpdateTime(now);

				rCategorySourceDao.updateByPrimaryKeySelective(_RCategorySource);
			}
		}
		List<RTagSource> rTagSources = rTagSourceDao.getListByItem(ItemTypeEnumForSource.VIDEO, eVideo.getId());
		if (Detect.notEmpty(rTagSources)) {
			for (RTagSource _RTagSource : rTagSources) {
				_RTagSource.setStatus(eVideo.getStatus());
				_RTagSource.setProgressStatus(dbEVideo.getProgressStatus());
				_RTagSource.setUpdateTime(now);

				rTagSourceDao.updateByPrimaryKeySelective(_RTagSource);
			}
		}

		List<Recommend> recommends = recommendDao.getListByItem(ItemTypeEnumForSource.VIDEO, eVideo.getId());
		if (Detect.notEmpty(recommends)) {
			for (Recommend _Recommend : recommends) {
				_Recommend.setStatus(eVideo.getStatus());
				_Recommend.setProgressStatus(dbEVideo.getProgressStatus());
				_Recommend.setUpdateTime(now);

				recommendDao.updateByPrimaryKeySelective(_Recommend);
			}
		}

		return eVideoDao.updateByPrimaryKeySelective(dbEVideo);
	}

	@Override
	public EVideo updateRelation(long childId, long parentId, boolean optype, UserContext userContext) throws UserContextException {
		EVideo childEVideo = eVideoDao.getById(childId);
		EVideo parentEVideo = eVideoDao.getById(parentId);
		if (childEVideo == null || parentEVideo == null) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}
		if (optype) {
			if (childEVideo.getParentId() != null && childEVideo.getParentId() > 0) {
				if (childEVideo.getParentId() == parentId) {
					throw new UserContextException("[已经添加了]");
				} else {
					EnhancedEVideo childEnhancedEVideo = new EnhancedEVideo(childEVideo);
					this.appendEnhancedParent(childEnhancedEVideo, userContext);

					throw new UserContextException("[已配置在(集合id:" + childEnhancedEVideo.getEnhancedParent().getId() + ",标题:" + childEnhancedEVideo.getEnhancedParent().getTitle() + ")视频集合中]");
				}
			}
			childEVideo.setParentId(parentId);
		} else {
			if (childEVideo.getParentId() == null || childEVideo.getParentId() < 1) {
				throw new UserContextException("[子视频不存在集合配置关系]");
			}
			if (childEVideo.getParentId() != null && childEVideo.getParentId() > 0 && childEVideo.getParentId() != parentId) {
				throw new UserContextException("[子视频不属于此集合配置]");
			}
			childEVideo.setParentId(0L);
		}
		return eVideoDao.updateByPrimaryKey(childEVideo);
	}
}
